#include "EvpModel.h"
#include "Common/DataStructureMacro.h"
#include "ssas_api.h"
#include "audio_service_api.h"
#define LOG_TAG "HMI"
#include "log_api.h"

#define EPV_AUDIO_ID AUDIO_5

typedef enum
{
    ALWAYS_OFF,
    ALWAYS_ON,
    EMERGENCY,
} MachineState;

static MachineState currentStatus;
static Option_U8    showFlag;
static uint32_t     twinkleCount;
static uint8_t      widget_visible_mask = 0;

static void init()
{
    currentStatus = ALWAYS_ON;
    showFlag.value_ = 0;
    showFlag.update_ = false;
    twinkleCount = 0;
}

static MachineState getNewState()
{
    MachineState newStatus = ALWAYS_OFF;
    int msgState = COM_MSG_INIT;
    Std_ReturnType comRet = E_NOT_OK;

    do
    {
        if(!isFinishSelfTest(SELF_TEST_3S))
        {
            newStatus = ALWAYS_ON;
            break;
        }

        msgState = get_message_state(COM_IC_EXTERIOR_LIGHTING_HS);
        if(COM_MSG_TIMEOUT == msgState || COM_MSG_INIT == msgState/*todo maybe remove*/)
        {
            newStatus = ALWAYS_OFF;
            break;
        }

        int rawData = 0;
        comRet = Com_ReceiveSignal(COM_SID_TrnSwAct, &rawData);
        if(E_NOT_OK == comRet)
        {
            newStatus = ALWAYS_OFF;
            break;
        }

        if(OFF == rawData)
        {
            newStatus = ALWAYS_OFF;
        }
        else
        {
            newStatus = EMERGENCY;
        }

    } while (false);
    
    return newStatus;
}

static void handlStateTransition(MachineState newStatus)
{
    if(newStatus != currentStatus)
    {
        switch (currentStatus)
        {
            case EMERGENCY:
            {
                twinkleCount = 0;
                stop_sound_request(EPV_AUDIO_ID);
                //todo stop popup
                break;
            }

            case ALWAYS_OFF:
            case ALWAYS_ON:
            {
                break;
            }
            
            default:
            {
                LOG_E("EVP leave unknow state : %d", currentStatus);
                break;
            }
        }

        currentStatus = newStatus;

        switch (currentStatus)
        {
            case EMERGENCY:
            {
                twinkleCount = 0;
                play_sound_request(EPV_AUDIO_ID, 500, 500, 90000);
                //todo play popup
                break;
            }

            case ALWAYS_OFF:
            case ALWAYS_ON:
            {
                break;
            }
            
            default:
            {
                LOG_E("EVP leave unknow state : %d", currentStatus);
                break;
            }
        }
    }
    
}

static void postprocess()
{
    switch (currentStatus)
    {
        case EMERGENCY:
        {
            uint8_t onoffState = OFF;
            onoffState = isOn_500ms(twinkleCount++);
            if(onoffState != showFlag.value_)
            {
                showFlag.value_ = onoffState;
                showFlag.update_ = true;
            }
            break;
        }

        case ALWAYS_OFF:
        {
            setOptionValue_U8(&showFlag, false);
            break;
        }

        case ALWAYS_ON:
        {
            setOptionValue_U8(&showFlag, true);
            break;
        }
        
        default:
        {
            LOG_E("EVP unknow state : %d", currentStatus);
            break;
        }
    }
}

static void run()
{
    MachineState newStatus = getNewState();
    handlStateTransition(newStatus);
    postprocess(); 
}

static void release()
{

}

EvpModel g_EvpModelInstance = {
    {
        init,
        run,
        release,
        MIN_PERIOD,
    },
};

// ----------------------------------View------------------------------
void refresh_tt12View(ItuElement* elememt, bool isUnconditional)
{
    if(isUnconditional || showFlag.update_)
    {
        showFlag.update_ = false;
        ituCheckBoxSetChecked((ITUCheckBox*)elememt->widget_, showFlag.value_);
    }
}

void reporting_self_validity_tt12View(ItuElement* elememt)
{
    uint8_t is_visible = (elememt && elememt->isVaild_) ? 0x01 : 0x00;
    widget_visible_mask <<= 1;
    widget_visible_mask |= is_visible;
}